using System;
using System.Collections.Generic;
using muduoDotNet;
using muduoDotNet.Messages;
using Google.Protobuf;

namespace muduoDotNet.Examples.ReflectionProtocol
{
    /// <summary>
    /// 反射协议客户端示例
    /// 演示如何使用反射特性自动注册和处理协议消息
    /// </summary>
    public class ReflectionProtocolClientExample
    {
        /// <summary>
        /// 运行客户端示例
        /// </summary>
        public static void RunExample()
        {
            Logger.Info("=== Reflection Protocol Client Example ===");
            
            var example = new ReflectionProtocolClientExample();
            example.Start();
            
            Logger.Info("Client running. Press Enter to stop...");
            Console.ReadLine();
            
            example.Stop();
            Logger.Info("Client stopped.");
        }
        
        /// <summary>
        /// 停止客户端
        /// </summary>
        public void Stop()
        {
            if (_client != null)
            {
                _client.Disconnect();
            }
            Logger.Info("Client disconnected.");
        }
        
        private TcpClient _client;
        private TcpConnection _connection;
        private Random _random = new Random();
        private string _clientId;
        private int _sentEchoRequests = 0;
        private int _receivedEchoResponses = 0;
        private int _sentHeartbeats = 0;
        private int _receivedHeartbeats = 0;

        /// <summary>
        /// 启动反射协议客户端
        /// </summary>
        public void Start()
        {
            Logger.Info("Starting Reflection Protocol Client Example...");
            Init();
        }

        /// <summary>
        /// 初始化客户端
        /// </summary>
        private void Init()
        {
            // 生成唯一客户端ID
            _clientId = Guid.NewGuid().ToString().Substring(0, 8);
            
            // 创建事件循环
            var loop = new EventLoop();
            
            // 创建TCP客户端
            _client = new TcpClient(loop, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888));
            
            // 设置连接回调
            _client.ConnectionCallback = OnConnection;
            
            // 启动连接
            _client.Connect();
            
            // 设置定时器定期发送心跳
            loop.AddTimer(SendHeartbeat, 3.0, 3.0); // 每3秒执行一次
            
            // 设置定时器定期发送Echo请求
            loop.AddTimer(SendEchoRequest, 5.0, 5.0); // 每5秒执行一次
            
            // 启动事件循环（阻塞调用）
            loop.Start();
        }

        /// <summary>
        /// 连接建立/断开回调
        /// </summary>
        private void OnConnection(TcpConnection connection)
        {
            if (connection.State == TcpConnectionState.Connected)
            {
                Logger.Info($"Connected to server: {connection.RemoteEndPoint}");
                
                // 保存连接引用
                _connection = connection;
                
                // 注册消息回调
                RegisterMessageCallbacks(connection);
                
                // 发送连接信息
                SendConnectionInfo();
                
                // 定期发送数据包
                connection.Loop.AddTimer(SendDataPacket, 8.0, 8.0);
                
                // 定期打印客户端状态
                connection.Loop.AddTimer(PrintClientStatus, 10.0, 10.0);
            }
            else
            {
                Logger.Info($"Disconnected from server");
                
                // 清理连接引用
                _connection = null;
            }
        }

        /// <summary>
        /// 注册消息回调
        /// </summary>
        private void RegisterMessageCallbacks(TcpConnection connection)
        {
            // 注册各种消息类型的回调处理函数
            connection.SetProtocolMessageCallback<EchoResponse>(HandleEchoResponse);
            connection.SetProtocolMessageCallback<Heartbeat>(HandleHeartbeat);
            connection.SetProtocolMessageCallback<StatusMessage>(HandleStatusMessage);
            connection.SetProtocolMessageCallback<DataPacket>(HandleDataPacket);
            
            Logger.Info("Registered message callbacks for client");
        }

        /// <summary>
        /// 发送连接信息
        /// </summary>
        private void SendConnectionInfo()
        {
            if (_connection != null && _connection.State == TcpConnectionState.Connected)
            {
                // 使用ConnectionInfo实际存在的字段
                var connectionInfo = new ConnectionInfo
                {
                    ConnectionId = _clientId,
                    RemoteAddress = _connection.RemoteEndPoint.ToString(),
                    ConnectTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                    ProtocolVersion = "1.0.0"
                };
                
                // ConnectionInfo没有Metadata字段，所以不添加额外信息
                
                _connection.SendProtobufMessage(connectionInfo);
                Logger.Info($"Sent connection info: {_clientId}");
            }
        }

        /// <summary>
        /// 发送Echo请求
        /// </summary>
        private void SendEchoRequest()
        {
            if (_connection != null && _connection.State == TcpConnectionState.Connected)
            {
                _sentEchoRequests++;
                
                // 生成随机消息内容
                string messageContent = GenerateRandomMessage();
                
                var echoRequest = new EchoRequest
                {
                    ClientId = _clientId,
                    Message = messageContent,
                    // EchoRequest没有SequenceId字段，使用client_id代替
                    Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                };
                
                _connection.SendProtobufMessage(echoRequest);
                Logger.Info($"Sent EchoRequest #{_sentEchoRequests}: '{messageContent}'");
            }
        }

        /// <summary>
        /// 发送心跳消息
        /// </summary>
        private void SendHeartbeat()
        {
            if (_connection != null && _connection.State == TcpConnectionState.Connected)
            {
                _sentHeartbeats++;
                
                var heartbeat = new Heartbeat
                {
                    NodeId = _clientId,
                    Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                };
                
                _connection.SendProtobufMessage(heartbeat);
                Logger.Debug($"Sent Heartbeat #{_sentHeartbeats}");
            }
        }

        /// <summary>
        /// 发送数据包
        /// </summary>
        private void SendDataPacket()
        {
            if (_connection != null && _connection.State == TcpConnectionState.Connected)
            {
                // 生成随机大小的数据
                int dataSize = _random.Next(10, 100);
                byte[] data = new byte[dataSize];
                _random.NextBytes(data);
                
                // 创建一个状态消息来替代不存在的DataPacket
                var statusMessage = new StatusMessage
                {
                    Type = StatusMessage.Types.StatusType.Info,
                    Message = "This is a test message from client",
                    Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
                };
                statusMessage.Metadata.Add("data_size", dataSize.ToString());
                statusMessage.Metadata.Add("message_id", Guid.NewGuid().ToString().Substring(0, 10));
                
                _connection.SendProtobufMessage(statusMessage);
                Logger.Info($"Sent StatusMessage: size={dataSize} bytes");
            }
        }

        /// <summary>
        /// 处理Echo响应
        /// </summary>
        private void HandleEchoResponse(TcpConnection connection, EchoResponse response)
        {
            _receivedEchoResponses++;
            Logger.Info($"Received EchoResponse #{_receivedEchoResponses}: '{response.Message}' (status: {response.StatusCode})");
        }

        /// <summary>
        /// 处理心跳响应
        /// </summary>
        private void HandleHeartbeat(TcpConnection connection, Heartbeat heartbeat)
        {
            _receivedHeartbeats++;
            long timeDifference = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - heartbeat.Timestamp;
            Logger.Debug($"Received Heartbeat #{_receivedHeartbeats} from {heartbeat.NodeId} (latency: {timeDifference}ms)");
        }

        /// <summary>
        /// 处理状态消息
        /// </summary>
        private void HandleStatusMessage(TcpConnection connection, StatusMessage status)
        {
            var typeStr = status.Type.ToString();
            Logger.Info($"Received StatusMessage [{typeStr}]: {status.Message}");
            
            if (status.Metadata.Count > 0)
            {
                foreach (var kv in status.Metadata)
                {
                    Logger.Debug($"  Metadata: {kv.Key} = {kv.Value}");
                }
            }
        }

        /// <summary>
        /// 处理数据包
        /// </summary>
        private void HandleDataPacket(TcpConnection connection, IMessage message)
        {
            Logger.Info($"Received message: type={message.GetType().Name}");
        }

        /// <summary>
        /// 生成随机消息
        /// </summary>
        private string GenerateRandomMessage()
        {
            string[] messages = new string[]
            {
                "Hello from Reflection Client",
                "Testing auto message handling",
                "Reflection is awesome!",
                "Protocol message with reflection",
                "Automatic handler registration",
                "How's the weather today?",
                "Random message " + _random.Next(1000),
                "C# reflection example",
                "This is a test message",
                "Enjoy using reflection!"
            };
            
            return messages[_random.Next(messages.Length)];
        }

        /// <summary>
        /// 打印客户端状态
        /// </summary>
        private void PrintClientStatus()
        {
            Logger.Info($"Client Status - ID: {_clientId}");
            Logger.Info($"  Echo: Sent={_sentEchoRequests}, Received={_receivedEchoResponses}");
            Logger.Info($"  Heartbeat: Sent={_sentHeartbeats}, Received={_receivedHeartbeats}");
            Logger.Info($"  Connection: {(_connection != null && _connection.State == TcpConnectionState.Connected ? "Connected" : "Disconnected")}");
        }
    }
}